home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 405_01 / flexpp / gen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-04-15  |  29.8 KB  |  1,289 lines

  1. /* gen - actual generation (writing) of flex scanners */
  2.  
  3. /*-
  4.  * Copyright (c) 1990 The Regents of the University of California.
  5.  * All rights reserved.
  6.  *
  7.  * This code is derived from software contributed to Berkeley by
  8.  * Vern Paxson.
  9.  * 
  10.  * The United States Government has rights in this work pursuant
  11.  * to contract no. DE-AC03-76SF00098 between the United States
  12.  * Department of Energy and the University of California.
  13.  *
  14.  * Redistribution and use in source and binary forms are permitted provided
  15.  * that: (1) source distributions retain this entire copyright notice and
  16.  * comment, and (2) distributions including binaries display the following
  17.  * acknowledgement:  ``This product includes software developed by the
  18.  * University of California, Berkeley and its contributors'' in the
  19.  * documentation or other materials provided with the distribution and in
  20.  * all advertising materials mentioning features or use of this software.
  21.  * Neither the name of the University nor the names of its contributors may
  22.  * be used to endorse or promote products derived from this software without
  23.  * specific prior written permission.
  24.  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  25.  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  26.  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  27.  */
  28.  
  29. #ifndef lint
  30. static char rcsid[] =
  31.     "@(#) $Header: /home/horse/u0/vern/flex/RCS/gen.c,v 2.12 91/03/28 12:01:38 vern Exp $ (LBL)";
  32. #endif
  33.  
  34. #include "flexdef.h"
  35.  
  36.  
  37. /* declare functions that have forward references */
  38.  
  39. void gen_next_state PROTO((int));
  40. void genecs PROTO(());
  41. void indent_put2s PROTO((char [], char []));
  42. void indent_puts PROTO((char []));
  43.  
  44.  
  45. static int indent_level = 0; /* each level is 4 spaces */
  46.  
  47. #define indent_up() (++indent_level)
  48. #define indent_down() (--indent_level)
  49. #define set_indent(indent_val) indent_level = indent_val
  50.  
  51. /* *everything* is done in terms of arrays starting at 1, so provide
  52.  * a null entry for the zero element of all C arrays
  53.  */
  54. static char C_short_decl[] = "static const short int %s[%d] =\n    {   0,\n";
  55. static char C_long_decl[] = "static const long int %s[%d] =\n    {   0,\n";
  56. static char C_state_decl[] =
  57.     "static const yy_state_type %s[%d] =\n    {   0,\n";
  58.  
  59.  
  60. /* indent to the current level */
  61.  
  62. void do_indent()
  63.  
  64.     {
  65.     register int i = indent_level * 4;
  66.  
  67.     while ( i >= 8 )
  68.     {
  69.     putchar( '\t' );
  70.     i -= 8;
  71.     }
  72.     
  73.     while ( i > 0 )
  74.     {
  75.     putchar( ' ' );
  76.     --i;
  77.     }
  78.     }
  79.  
  80.  
  81. /* generate the code to keep backtracking information */
  82.  
  83. void gen_backtracking()
  84.  
  85.     {
  86.     if ( reject || num_backtracking == 0 )
  87.     return;
  88.  
  89.     if ( fullspd )
  90.     indent_puts( "if ( yy_current_state[-1].yy_nxt )" );
  91.     else
  92.     indent_puts( "if ( yy_accept[yy_current_state] )" );
  93.  
  94.     indent_up();
  95.     indent_puts( "{" );
  96.     indent_puts( "yy_last_accepting_state = yy_current_state;" );
  97.     indent_puts( "yy_last_accepting_cpos = yy_cp;" );
  98.     indent_puts( "}" );
  99.     indent_down();
  100.     }
  101.  
  102.  
  103. /* generate the code to perform the backtrack */
  104.  
  105. void gen_bt_action()
  106.  
  107.     {
  108.     if ( reject || num_backtracking == 0 )
  109.     return;
  110.  
  111.     set_indent( 3 );
  112.  
  113.     indent_puts( "case 0: /* must backtrack */" );
  114.     indent_puts( "/* undo the effects of YY_DO_BEFORE_ACTION */" );
  115.     indent_puts( "*yy_cp = yy_hold_char;" );
  116.  
  117.     if ( fullspd || fulltbl )
  118.     indent_puts( "yy_cp = yy_last_accepting_cpos + 1;" );
  119.     else
  120.     /* backtracking info for compressed tables is taken \after/
  121.      * yy_cp has been incremented for the next state
  122.      */
  123.     indent_puts( "yy_cp = yy_last_accepting_cpos;" );
  124.  
  125.     indent_puts( "yy_current_state = yy_last_accepting_state;" );
  126.     indent_puts( "goto yy_find_action;" );
  127.     putchar( '\n' );
  128.  
  129.     set_indent( 0 );
  130.     }
  131.  
  132.  
  133. /* genctbl - generates full speed compressed transition table
  134.  *
  135.  * synopsis
  136.  *     genctbl();
  137.  */
  138.  
  139. void genctbl()
  140.  
  141.     {
  142.     register int i;
  143.     int end_of_buffer_action = num_rules + 1;
  144.  
  145.     /* table of verify for transition and offset to next state */
  146.     printf( "static const struct yy_trans_info yy_transition[%d] =\n",
  147.         tblend + numecs + 1 );
  148.     printf( "    {\n" );
  149.     
  150.     /* We want the transition to be represented as the offset to the
  151.      * next state, not the actual state number, which is what it currently is.
  152.      * The offset is base[nxt[i]] - base[chk[i]].  That's just the
  153.      * difference between the starting points of the two involved states
  154.      * (to - from).
  155.      *
  156.      * first, though, we need to find some way to put in our end-of-buffer
  157.      * flags and states.  We do this by making a state with absolutely no
  158.      * transitions.  We put it at the end of the table.
  159.      */
  160.     /* at this point, we're guaranteed that there's enough room in nxt[]
  161.      * and chk[] to hold tblend + numecs entries.  We need just two slots.
  162.      * One for the action and one for the end-of-buffer transition.  We
  163.      * now *assume* that we're guaranteed the only character we'll try to
  164.      * index this nxt/chk pair with is EOB, i.e., 0, so we don't have to
  165.      * make sure there's room for jam entries for other characters.
  166.      */
  167.  
  168.     base[lastdfa + 1] = tblend + 2;
  169.     nxt[tblend + 1] = end_of_buffer_action;
  170.     chk[tblend + 1] = numecs + 1;
  171.     chk[tblend + 2] = 1; /* anything but EOB */
  172.     nxt[tblend + 2] = 0; /* so that "make test" won't show arb. differences */
  173.  
  174.     /* make sure every state has a end-of-buffer transition and an action # */
  175.     for ( i = 0; i <= lastdfa; ++i )
  176.     {
  177.     register int anum = dfaacc[i].dfaacc_state;
  178.  
  179.     chk[base[i]] = EOB_POSITION;
  180.     chk[base[i] - 1] = ACTION_POSITION;
  181.     nxt[base[i] - 1] = anum;    /* action number */
  182.     }
  183.  
  184.     for ( i = 0; i <= tblend; ++i )
  185.     {
  186.     if ( chk[i] == EOB_POSITION )
  187.         transition_struct_out( 0, base[lastdfa + 1] - i );
  188.  
  189.     else if ( chk[i] == ACTION_POSITION )
  190.         transition_struct_out( 0, nxt[i] );
  191.  
  192.     else if ( chk[i] > numecs || chk[i] == 0 )
  193.         transition_struct_out( 0, 0 );        /* unused slot */
  194.  
  195.     else    /* verify, transition */
  196.         transition_struct_out( chk[i], base[nxt[i]] - (i - chk[i]) );
  197.     }
  198.  
  199.  
  200.     /* here's the final, end-of-buffer state */
  201.     transition_struct_out( chk[tblend + 1], nxt[tblend + 1] );
  202.     transition_struct_out( chk[tblend + 2], nxt[tblend + 2] );
  203.  
  204.     printf( "    };\n" );
  205.     printf( "\n" );
  206.  
  207.     /* table of pointers to start states */
  208.     printf( "static const struct yy_trans_info *yy_start_state_list[%d] =\n",
  209.         lastsc * 2 + 1 );
  210.     printf( "    {\n" );
  211.  
  212.     for ( i = 0; i <= lastsc * 2; ++i )
  213.     printf( "    &yy_transition[%d],\n", base[i] );
  214.  
  215.     dataend();
  216.  
  217.     if ( useecs )
  218.     genecs();
  219.     }
  220.  
  221.  
  222. /* generate equivalence-class tables */
  223.  
  224. void genecs()
  225.  
  226.     {
  227.     register int i, j;
  228.     static char C_char_decl[] = "static const %s %s[%d] =\n    {   0,\n";
  229.     int numrows;
  230.     Char clower();
  231.  
  232.     if ( numecs < csize )
  233.     printf( C_char_decl, "YY_CHAR", "yy_ec", csize );
  234.     else
  235.     printf( C_char_decl, "short", "yy_ec", csize );
  236.  
  237.     for ( i = 1; i < csize; ++i )
  238.     {
  239.     if ( caseins && (i >= 'A') && (i <= 'Z') )
  240.         ecgroup[i] = ecgroup[clower( i )];
  241.  
  242.     ecgroup[i] = abs( ecgroup[i] );
  243.     mkdata( ecgroup[i] );
  244.     }
  245.  
  246.     dataend();
  247.  
  248.     if ( trace )
  249.     {
  250.     char *readable_form();
  251.  
  252.     fputs( "\n\nEquivalence Classes:\n\n", stderr );
  253.  
  254.     numrows = csize / 8;
  255.  
  256.     for ( j = 0; j < numrows; ++j )
  257.         {
  258.         for ( i = j; i < csize; i = i + numrows )
  259.         {
  260.         fprintf( stderr, "%4s = %-2d", readable_form( i ), ecgroup[i] );
  261.  
  262.         putc( ' ', stderr );
  263.         }
  264.  
  265.         putc( '\n', stderr );
  266.         }
  267.     }
  268.     }
  269.  
  270.  
  271. /* generate the code to find the action number */
  272.  
  273. void gen_find_action()
  274.  
  275.     {
  276.     if ( fullspd )
  277.     indent_puts( "yy_act = yy_current_state[-1].yy_nxt;" );
  278.  
  279.     else if ( fulltbl )
  280.     indent_puts( "yy_act = yy_accept[yy_current_state];" );
  281.  
  282.     else if ( reject )
  283.     {
  284.     indent_puts( "yy_current_state = *--yy_state_ptr;" );
  285.     indent_puts( "yy_lp = yy_accept[yy_current_state];" );
  286.  
  287.     puts( "find_rule: /* we branch to this label when backtracking */" );
  288.  
  289.     indent_puts( "for ( ; ; ) /* until we find what rule we matched */" );
  290.  
  291.     indent_up();
  292.  
  293.     indent_puts( "{" );
  294.  
  295.     indent_puts( "if ( yy_lp && yy_lp < yy_accept[yy_current_state + 1] )" );
  296.     indent_up();
  297.     indent_puts( "{" );
  298.     indent_puts( "yy_act = yy_acclist[yy_lp];" );
  299.  
  300.     if ( variable_trailing_context_rules )
  301.         {
  302.         indent_puts( "if ( yy_act & YY_TRAILING_HEAD_MASK ||" );
  303.         indent_puts( "     yy_looking_for_trail_begin )" );
  304.         indent_up();
  305.         indent_puts( "{" );
  306.  
  307.         indent_puts( "if ( yy_act == yy_looking_for_trail_begin )" );
  308.         indent_up();
  309.         indent_puts( "{" );
  310.         indent_puts( "yy_looking_for_trail_begin = 0;" );
  311.         indent_puts( "yy_act &= ~YY_TRAILING_HEAD_MASK;" );
  312.         indent_puts( "break;" );
  313.         indent_puts( "}" );
  314.         indent_down();
  315.  
  316.         indent_puts( "}" );
  317.         indent_down();
  318.  
  319.         indent_puts( "else if ( yy_act & YY_TRAILING_MASK )" );
  320.         indent_up();
  321.         indent_puts( "{" );
  322.         indent_puts(
  323.         "yy_looking_for_trail_begin = yy_act & ~YY_TRAILING_MASK;" );
  324.         indent_puts(
  325.         "yy_looking_for_trail_begin |= YY_TRAILING_HEAD_MASK;" );
  326.  
  327.         if ( real_reject )
  328.         {
  329.         /* remember matched text in case we back up due to REJECT */
  330.         indent_puts( "yy_full_match = yy_cp;" );
  331.         indent_puts( "yy_full_state = yy_state_ptr;" );
  332.         indent_puts( "yy_full_lp = yy_lp;" );
  333.         }
  334.  
  335.         indent_puts( "}" );
  336.         indent_down();
  337.  
  338.         indent_puts( "else" );
  339.         indent_up();
  340.         indent_puts( "{" );
  341.         indent_puts( "yy_full_match = yy_cp;" );
  342.         indent_puts( "yy_full_state = yy_state_ptr;" );
  343.         indent_puts( "yy_full_lp = yy_lp;" );
  344.         indent_puts( "break;" );
  345.         indent_puts( "}" );
  346.         indent_down();
  347.  
  348.         indent_puts( "++yy_lp;" );
  349.         indent_puts( "goto find_rule;" );
  350.         }
  351.  
  352.     else
  353.         {
  354.         /* remember matched text in case we back up due to trailing context
  355.          * plus REJECT
  356.          */
  357.         indent_up();
  358.         indent_puts( "{" );
  359.         indent_puts( "yy_full_match = yy_cp;" );
  360.         indent_puts( "break;" );
  361.         indent_puts( "}" );
  362.         indent_down();
  363.         }
  364.  
  365.     indent_puts( "}" );
  366.     indent_down();
  367.  
  368.     indent_puts( "--yy_cp;" );
  369.  
  370.     /* we could consolidate the following two lines with those at
  371.      * the beginning, but at the cost of complaints that we're
  372.      * branching inside a loop
  373.      */
  374.     indent_puts( "yy_current_state = *--yy_state_ptr;" );
  375.     indent_puts( "yy_lp = yy_accept[yy_current_state];" );
  376.  
  377.     indent_puts( "}" );
  378.  
  379.     indent_down();
  380.     }
  381.  
  382.     else
  383.     /* compressed */
  384.     indent_puts( "yy_act = yy_accept[yy_current_state];" );
  385.     }
  386.  
  387.  
  388. /* genftbl - generates full transition table
  389.  *
  390.  * synopsis
  391.  *     genftbl();
  392.  */
  393.  
  394. void genftbl()
  395.  
  396.     {
  397.     register int i;
  398.     int end_of_buffer_action = num_rules + 1;
  399.  
  400.     printf( C_short_decl, "yy_accept", lastdfa + 1 );
  401.  
  402.  
  403.     dfaacc[end_of_buffer_state].dfaacc_state = end_of_buffer_action;
  404.  
  405.     for ( i = 1; i <= lastdfa; ++i )
  406.     {
  407.     register int anum = dfaacc[i].dfaacc_state;
  408.  
  409.     mkdata( anum );
  410.  
  411.     if ( trace && anum )
  412.         fprintf( stderr, "state # %d accepts: [%d]\n", i, anum );
  413.     }
  414.  
  415.     dataend();
  416.  
  417.     if ( useecs )
  418.     genecs();
  419.  
  420.     /* don't have to dump the actual full table entries - they were created
  421.      * on-the-fly
  422.      */
  423.     }
  424.  
  425.  
  426. /* generate the code to find the next compressed-table state */
  427.  
  428. void gen_next_compressed_state( char_map )
  429. char *char_map;
  430.  
  431.     {
  432.     indent_put2s( "register YY_CHAR yy_c = %s;", char_map );
  433.  
  434.     /* save the backtracking info \before/ computing the next state
  435.      * because we always compute one more state than needed - we
  436.      * always proceed until we reach a jam state
  437.      */
  438.     gen_backtracking();
  439.  
  440.     indent_puts(
  441.     "while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )" );
  442.     indent_up();
  443.     indent_puts( "{" );
  444.     indent_puts( "yy_current_state = yy_def[yy_current_state];" );
  445.  
  446.     if ( usemecs )
  447.     {
  448.     /* we've arrange it so that templates are never chained
  449.      * to one another.  This means we can afford make a
  450.      * very simple test to see if we need to convert to
  451.      * yy_c's meta-equivalence class without worrying
  452.      * about erroneously looking up the meta-equivalence
  453.      * class twice
  454.      */
  455.     do_indent();
  456.     /* lastdfa + 2 is the beginning of the templates */
  457.     printf( "if ( yy_current_state >= %d )\n", lastdfa + 2 );
  458.  
  459.     indent_up();
  460.     indent_puts( "yy_c = yy_meta[yy_c];" );
  461.     indent_down();
  462.     }
  463.  
  464.     indent_puts( "}" );
  465.     indent_down();
  466.  
  467.     indent_puts(
  468.     "yy_current_state = yy_nxt[yy_base[yy_current_state] + yy_c];" );
  469.     }
  470.  
  471.  
  472. /* generate the code to find the next match */
  473.  
  474. void gen_next_match()
  475.  
  476.     {
  477.     /* NOTE - changes in here should be reflected in gen_next_state() and
  478.      * gen_NUL_trans()
  479.      */
  480.     char *char_map = useecs ? "yy_ec[*yy_cp]" : "*yy_cp";
  481.     char *char_map_2 = useecs ? "yy_ec[*++yy_cp]" : "*++yy_cp";
  482.     
  483.     if ( fulltbl )
  484.     {
  485.     indent_put2s(
  486.         "while ( (yy_current_state = yy_nxt[yy_current_state][%s]) > 0 )",
  487.         char_map );
  488.  
  489.     indent_up();
  490.  
  491.     if ( num_backtracking > 0 )
  492.         {
  493.         indent_puts( "{" );
  494.         gen_backtracking();
  495.         putchar( '\n' );
  496.         }
  497.  
  498.     indent_puts( "++yy_cp;" );
  499.  
  500.     if ( num_backtracking > 0 )
  501.         indent_puts( "}" );
  502.  
  503.     indent_down();
  504.  
  505.     putchar( '\n' );
  506.     indent_puts( "yy_current_state = -yy_current_state;" );
  507.     }
  508.  
  509.     else if ( fullspd )
  510.     {
  511.     indent_puts( "{" );
  512.     indent_puts( "register const struct yy_trans_info *yy_trans_info;\n" );
  513.     indent_puts( "register YY_CHAR yy_c;\n" );
  514.     indent_put2s( "for ( yy_c = %s;", char_map );
  515.     indent_puts(
  516.     "      (yy_trans_info = &yy_current_state[yy_c])->yy_verify == yy_c;" );
  517.     indent_put2s( "      yy_c = %s )", char_map_2 );
  518.  
  519.     indent_up();
  520.  
  521.     if ( num_backtracking > 0 )
  522.         indent_puts( "{" );
  523.  
  524.     indent_puts( "yy_current_state += yy_trans_info->yy_nxt;" );
  525.  
  526.     if ( num_backtracking > 0 )
  527.         {
  528.         putchar( '\n' );
  529.         gen_backtracking();
  530.         indent_puts( "}" );
  531.         }
  532.  
  533.     indent_down();
  534.     indent_puts( "}" );
  535.     }
  536.  
  537.     else
  538.     { /* compressed */
  539.     indent_puts( "do" );
  540.  
  541.     indent_up();
  542.     indent_puts( "{" );
  543.  
  544.     gen_next_state( false );
  545.  
  546.     indent_puts( "++yy_cp;" );
  547.  
  548.     indent_puts( "}" );
  549.     indent_down();
  550.  
  551.     do_indent();
  552.  
  553.     if ( interactive )
  554.         printf( "while ( yy_base[yy_current_state] != %d );\n", jambase );
  555.     else
  556.         printf( "while ( yy_current_state != %d );\n", jamstate );
  557.  
  558.     if ( ! reject && ! interactive )
  559.         {
  560.         /* do the guaranteed-needed backtrack to figure out the match */
  561.         indent_puts( "yy_cp = yy_last_accepting_cpos;" );
  562.         indent_puts( "yy_current_state = yy_last_accepting_state;" );
  563.         }
  564.     }
  565.     }
  566.  
  567.  
  568. /* generate the code to find the next state */
  569.  
  570. void gen_next_state( worry_about_NULs )
  571. int worry_about_NULs;
  572.  
  573.     { /* NOTE - changes in here should be reflected in get_next_match() */
  574.     char char_map[256];
  575.  
  576.     if ( worry_about_NULs && ! nultrans )
  577.     {
  578.     if ( useecs )
  579.         (void) sprintf( char_map, "(*yy_cp ? yy_ec[*yy_cp] : %d)", NUL_ec );
  580.     else
  581.         (void) sprintf( char_map, "(*yy_cp ? *yy_cp : %d)", NUL_ec );
  582.     }
  583.  
  584.     else
  585.     (void) strcpy( char_map, useecs ? "yy_ec[*yy_cp]" : "*yy_cp" );
  586.  
  587.     if ( worry_about_NULs && nultrans )
  588.     {
  589.     if ( ! fulltbl && ! fullspd )
  590.         /* compressed tables backtrack *before* they match */
  591.         gen_backtracking();
  592.  
  593.     indent_puts( "if ( *yy_cp )" );
  594.     indent_up();
  595.     indent_puts( "{" );
  596.     }
  597.    
  598.     if ( fulltbl )
  599.     indent_put2s( "yy_current_state = yy_nxt[yy_current_state][%s];", 
  600.         char_map );
  601.     
  602.     else if ( fullspd )
  603.     indent_put2s( "yy_current_state += yy_current_state[%s].yy_nxt;",
  604.             char_map );
  605.  
  606.     else
  607.     gen_next_compressed_state( char_map );
  608.  
  609.     if ( worry_about_NULs && nultrans )
  610.     {
  611.     indent_puts( "}" );
  612.     indent_down();
  613.     indent_puts( "else" );
  614.     indent_up();
  615.     indent_puts( "yy_current_state = yy_NUL_trans[yy_current_state];" );
  616.     indent_down();
  617.     }
  618.     
  619.     if ( fullspd || fulltbl )
  620.     gen_backtracking();
  621.  
  622.     if ( reject )
  623.     indent_puts( "*yy_state_ptr++ = yy_current_state;" );
  624.     }
  625.  
  626.  
  627. /* generate the code to make a NUL transition */
  628.  
  629. void gen_NUL_trans()
  630.  
  631.     { /* NOTE - changes in here should be reflected in get_next_match() */
  632.     int need_backtracking = (num_backtracking > 0 && ! reject);
  633.  
  634.     if ( need_backtracking )
  635.     /* we'll need yy_cp lying around for the gen_backtracking() */
  636.     indent_puts( "register YY_CHAR *yy_cp = yy_c_buf_p;" );
  637.  
  638.     putchar( '\n' );
  639.  
  640.     if ( nultrans )
  641.     {
  642.     indent_puts( "yy_current_state = yy_NUL_trans[yy_current_state];" );
  643.     indent_puts( "yy_is_jam = (yy_current_state == 0);" );
  644.     }
  645.  
  646.     else if ( fulltbl )
  647.     {
  648.     do_indent();
  649.     printf( "yy_current_state = yy_nxt[yy_current_state][%d];\n",
  650.         NUL_ec );
  651.     indent_puts( "yy_is_jam = (yy_current_state <= 0);" );
  652.     }
  653.  
  654.     else if ( fullspd )
  655.     {
  656.     do_indent();
  657.     printf( "register int yy_c = %d;\n", NUL_ec );
  658.  
  659.     indent_puts(
  660.         "register const struct yy_trans_info *yy_trans_info;\n" );
  661.     indent_puts( "yy_trans_info = &yy_current_state[yy_c];" );
  662.     indent_puts( "yy_current_state += yy_trans_info->yy_nxt;" );
  663.  
  664.     indent_puts( "yy_is_jam = (yy_trans_info->yy_verify != yy_c);" );
  665.     }
  666.  
  667.     else
  668.     {
  669.     char NUL_ec_str[20];
  670.  
  671.     (void) sprintf( NUL_ec_str, "%d", NUL_ec );
  672.     gen_next_compressed_state( NUL_ec_str );
  673.  
  674.     if ( reject )
  675.         indent_puts( "*yy_state_ptr++ = yy_current_state;" );
  676.  
  677.     do_indent();
  678.  
  679.      printf( "yy_is_jam = (yy_current_state == %d);\n", jamstate );
  680.     }
  681.  
  682.     /* if we've entered an accepting state, backtrack; note that
  683.      * compressed tables have *already* done such backtracking, so
  684.      * we needn't bother with it again
  685.      */
  686.     if ( need_backtracking && (fullspd || fulltbl) )
  687.     {
  688.     putchar( '\n' );
  689.     indent_puts( "if ( ! yy_is_jam )" );
  690.     indent_up();
  691.     indent_puts( "{" );
  692.     gen_backtracking();
  693.     indent_puts( "}" );
  694.     indent_down();
  695.     }
  696.     }
  697.  
  698.  
  699. /* generate the code to find the start state */
  700.  
  701. void gen_start_state()
  702.  
  703.     {
  704.     if ( fullspd )
  705.     indent_put2s( "yy_current_state = yy_start_state_list[yy_start%s];",
  706.         bol_needed ? " + (yy_bp[-1] == '\\n' ? 1 : 0)" : "" );
  707.  
  708.     else
  709.     {
  710.     indent_puts( "yy_current_state = yy_start;" );
  711.  
  712.     if ( bol_needed )
  713.         {
  714.         indent_puts( "if ( yy_bp[-1] == '\\n' )" );
  715.         indent_up();
  716.         indent_puts( "++yy_current_state;" );
  717.         indent_down();
  718.         }
  719.  
  720.     if ( reject )
  721.         {
  722.         /* set up for storing up states */
  723.         indent_puts( "yy_state_ptr = yy_state_buf;" );
  724.         indent_puts( "*yy_state_ptr++ = yy_current_state;" );
  725.         }
  726.     }
  727.     }
  728.  
  729.  
  730. /* gentabs - generate data statements for the transition tables
  731.  *
  732.  * synopsis
  733.  *    gentabs();
  734.  */
  735.  
  736. void gentabs()
  737.  
  738.     {
  739.     int i, j, k, *accset, nacc, *acc_array, total_states;
  740.     int end_of_buffer_action = num_rules + 1;
  741.  
  742.     /* *everything* is done in terms of arrays starting at 1, so provide
  743.      * a null entry for the zero element of all C arrays
  744.      */
  745.     static char C_char_decl[] =
  746.     "static const YY_CHAR %s[%d] =\n    {   0,\n";
  747.  
  748.     acc_array = allocate_integer_array( current_max_dfas );
  749.     nummt = 0;
  750.  
  751.     /* the compressed table format jams by entering the "jam state",
  752.      * losing information about the previous state in the process.
  753.      * In order to recover the previous state, we effectively need
  754.      * to keep backtracking information.
  755.      */
  756.     ++num_backtracking;
  757.  
  758.     if ( reject )
  759.     {
  760.     /* write out accepting list and pointer list
  761.      *
  762.      * first we generate the "yy_acclist" array.  In the process, we compute
  763.      * the indices that will go into the "yy_accept" array, and save the
  764.      * indices in the dfaacc array
  765.      */
  766.     int EOB_accepting_list[2];
  767.  
  768.     /* set up accepting structures for the End Of Buffer state */
  769.     EOB_accepting_list[0] = 0;
  770.     EOB_accepting_list[1] = end_of_buffer_action;
  771.     accsiz[end_of_buffer_state] = 1;
  772.     dfaacc[end_of_buffer_state].dfaacc_set = EOB_accepting_list;
  773.  
  774.     printf( C_short_decl, "yy_acclist", max( numas, 1 ) + 1 );
  775.  
  776.     j = 1;    /* index into "yy_acclist" array */
  777.  
  778.     for ( i = 1; i <= lastdfa; ++i )
  779.         {
  780.         acc_array[i] = j;
  781.  
  782.         if ( accsiz[i] != 0 )
  783.         {
  784.         accset = dfaacc[i].dfaacc_set;
  785.         nacc = accsiz[i];
  786.  
  787.         if ( trace )
  788.             fprintf( stderr, "state # %d accepts: ", i );
  789.  
  790.         for ( k = 1; k <= nacc; ++k )
  791.             {
  792.             int accnum = accset[k];
  793.  
  794.             ++j;
  795.  
  796.             if ( variable_trailing_context_rules &&
  797.              ! (accnum & YY_TRAILING_HEAD_MASK) &&
  798.              accnum > 0 && accnum <= num_rules &&
  799.              rule_type[accnum] == RULE_VARIABLE )
  800.             {
  801.             /* special hack to flag accepting number as part
  802.              * of trailing context rule
  803.              */
  804.             accnum |= YY_TRAILING_MASK;
  805.             }
  806.  
  807.             mkdata( accnum );
  808.  
  809.             if ( trace )
  810.             {
  811.             fprintf( stderr, "[%d]", accset[k] );
  812.  
  813.             if ( k < nacc )
  814.                 fputs( ", ", stderr );
  815.             else
  816.                 putc( '\n', stderr );
  817.             }
  818.             }
  819.         }
  820.         }
  821.  
  822.     /* add accepting number for the "jam" state */
  823.     acc_array[i] = j;
  824.  
  825.     dataend();
  826.     }
  827.  
  828.     else
  829.     {
  830.     dfaacc[end_of_buffer_state].dfaacc_state = end_of_buffer_action;
  831.  
  832.     for ( i = 1; i <= lastdfa; ++i )
  833.         acc_array[i] = dfaacc[i].dfaacc_state;
  834.  
  835.     /* add accepting number for jam state */
  836.     acc_array[i] = 0;
  837.     }
  838.  
  839.     /* spit out "yy_accept" array.  If we're doing "reject", it'll be pointers
  840.      * into the "yy_acclist" array.  Otherwise it's actual accepting numbers.
  841.      * In either case, we just dump the numbers.
  842.      */
  843.  
  844.     /* "lastdfa + 2" is the size of "yy_accept"; includes room for C arrays
  845.      * beginning at 0 and for "jam" state
  846.      */
  847.     k = lastdfa + 2;
  848.  
  849.     if ( reject )
  850.     /* we put a "cap" on the table associating lists of accepting
  851.      * numbers with state numbers.  This is needed because we tell
  852.      * where the end of an accepting list is by looking at where
  853.      * the list for the next state starts.
  854.      */
  855.     ++k;
  856.  
  857.     printf( C_short_decl, "yy_accept", k );
  858.  
  859.     for ( i = 1; i <= lastdfa; ++i )
  860.     {
  861.     mkdata( acc_array[i] );
  862.  
  863.     if ( ! reject && trace && acc_array[i] )
  864.         fprintf( stderr, "state # %d accepts: [%d]\n", i, acc_array[i] );
  865.     }
  866.  
  867.     /* add entry for "jam" state */
  868.     mkdata( acc_array[i] );
  869.  
  870.     if ( reject )
  871.     /* add "cap" for the list */
  872.     mkdata( acc_array[i] );
  873.  
  874.     dataend();
  875.  
  876.     if ( useecs )
  877.     genecs();
  878.  
  879.     if ( usemecs )
  880.     {
  881.     /* write out meta-equivalence classes (used to index templates with) */
  882.  
  883.     if ( trace )
  884.         fputs( "\n\nMeta-Equivalence Classes:\n", stderr );
  885.  
  886.     printf( C_char_decl, "yy_meta", numecs + 1 );
  887.  
  888.     for ( i = 1; i <= numecs; ++i )
  889.         {
  890.         if ( trace )
  891.         fprintf( stderr, "%d = %d\n", i, abs( tecbck[i] ) );
  892.  
  893.         mkdata( abs( tecbck[i] ) );
  894.         }
  895.  
  896.     dataend();
  897.     }
  898.  
  899.     total_states = lastdfa + numtemps;
  900.  
  901.     printf( tblend > MAX_SHORT ? C_long_decl : C_short_decl,
  902.         "yy_base", total_states + 1 );
  903.  
  904.     for ( i = 1; i <= lastdfa; ++i )
  905.     {
  906.     register int d = def[i];
  907.  
  908.     if ( base[i] == JAMSTATE )
  909.         base[i] = jambase;
  910.  
  911.     if ( d == JAMSTATE )
  912.         def[i] = jamstate;
  913.  
  914.     else if ( d < 0 )
  915.         {
  916.         /* template reference */
  917.         ++tmpuses;
  918.         def[i] = lastdfa - d + 1;
  919.         }
  920.  
  921.     mkdata( base[i] );
  922.     }
  923.  
  924.     /* generate jam state's base index */
  925.     mkdata( base[i] );
  926.  
  927.     for ( ++i /* skip jam state */; i <= total_states; ++i )
  928.     {
  929.     mkdata( base[i] );
  930.     def[i] = jamstate;
  931.     }
  932.  
  933.     dataend();
  934.  
  935.     printf( tblend > MAX_SHORT ? C_long_decl : C_short_decl,
  936.         "yy_def", total_states + 1 );
  937.  
  938.     for ( i = 1; i <= total_states; ++i )
  939.     mkdata( def[i] );
  940.  
  941.     dataend();
  942.  
  943.     printf( lastdfa > MAX_SHORT ? C_long_decl : C_short_decl,
  944.         "yy_nxt", tblend + 1 );
  945.  
  946.     for ( i = 1; i <= tblend; ++i )
  947.     {
  948.     if ( nxt[i] == 0 || chk[i] == 0 )
  949.         nxt[i] = jamstate;    /* new state is the JAM state */
  950.  
  951.     mkdata( nxt[i] );
  952.     }
  953.  
  954.     dataend();
  955.  
  956.     printf( lastdfa > MAX_SHORT ? C_long_decl : C_short_decl,
  957.         "yy_chk", tblend + 1 );
  958.  
  959.     for ( i = 1; i <= tblend; ++i )
  960.     {
  961.     if ( chk[i] == 0 )
  962.         ++nummt;
  963.  
  964.     mkdata( chk[i] );
  965.     }
  966.  
  967.     dataend();
  968.     }
  969.  
  970.  
  971. /* write out a formatted string (with a secondary string argument) at the
  972.  * current indentation level, adding a final newline
  973.  */
  974.  
  975. void indent_put2s( fmt, arg )
  976. char fmt[], arg[];
  977.  
  978.     {
  979.     do_indent();
  980.     printf( fmt, arg );
  981.     putchar( '\n' );
  982.     }
  983.  
  984.  
  985. /* write out a string at the current indentation level, adding a final
  986.  * newline
  987.  */
  988.  
  989. void indent_puts( str )
  990. char str[];
  991.  
  992.     {
  993.     do_indent();
  994.     puts( str );
  995.     }
  996.  
  997.  
  998. /* make_tables - generate transition tables
  999.  *
  1000.  * synopsis
  1001.  *     make_tables();
  1002.  *
  1003.  * Generates transition tables and finishes generating output file
  1004.  */
  1005.  
  1006. void make_tables()
  1007.  
  1008.     {
  1009.     register int i;
  1010.     int did_eof_rule = false;
  1011.  
  1012.     skelout();
  1013.  
  1014.     /* first, take care of YY_DO_BEFORE_ACTION depending on yymore being used */
  1015.     set_indent( 2 );
  1016.  
  1017.     if ( yymore_used )
  1018.     {
  1019.     indent_puts( "yy___text -= yy_more_len; \\" );
  1020.     indent_puts( "yy___leng = yy_cp - yy___text; \\" );
  1021.     }
  1022.  
  1023.     else
  1024.     indent_puts( "yy___leng = yy_cp - yy_bp; \\" );
  1025.  
  1026.     set_indent( 0 );
  1027.     
  1028.     skelout();
  1029.  
  1030.  
  1031.     printf( "#define YY_END_OF_BUFFER %d\n", num_rules + 1 );
  1032.  
  1033.     if ( fullspd )
  1034.     { /* need to define the transet type as a size large
  1035.        * enough to hold the biggest offset
  1036.        */
  1037.     int total_table_size = tblend + numecs + 1;
  1038.     char *trans_offset_type =
  1039.         total_table_size > MAX_SHORT ? "long" : "short";
  1040.  
  1041.     set_indent( 0 );
  1042.     indent_puts( "struct yy_trans_info" );
  1043.     indent_up();
  1044.         indent_puts( "{" );
  1045.         indent_puts( "short yy_verify;" );
  1046.  
  1047.         /* in cases where its sister yy_verify *is* a "yes, there is a
  1048.      * transition", yy_nxt is the offset (in records) to the next state.
  1049.      * In most cases where there is no transition, the value of yy_nxt
  1050.      * is irrelevant.  If yy_nxt is the -1th  record of a state, though,
  1051.      * then yy_nxt is the action number for that state
  1052.          */
  1053.  
  1054.         indent_put2s( "%s yy_nxt;", trans_offset_type );
  1055.         indent_puts( "};" );
  1056.     indent_down();
  1057.  
  1058.     indent_puts( "typedef const struct yy_trans_info *yy_state_type;" );
  1059.     }
  1060.     
  1061.     else
  1062.     indent_puts( "typedef int yy_state_type;" );
  1063.  
  1064.     if ( fullspd )
  1065.     genctbl();
  1066.  
  1067.     else if ( fulltbl )
  1068.     genftbl();
  1069.  
  1070.     else
  1071.     gentabs();
  1072.  
  1073.     if ( num_backtracking > 0 )
  1074.     {
  1075.     indent_puts( "static yy_state_type yy_last_accepting_state;" );
  1076.     indent_puts( "static YY_CHAR *yy_last_accepting_cpos;\n" );
  1077.     }
  1078.  
  1079.     if ( nultrans )
  1080.     {
  1081.     printf( C_state_decl, "yy_NUL_trans", lastdfa + 1 );
  1082.  
  1083.     for ( i = 1; i <= lastdfa; ++i )
  1084.         {
  1085.         if ( fullspd )
  1086.         {
  1087.         if ( nultrans )
  1088.             printf( "    &yy_transition[%d],\n", base[i] );
  1089.         else
  1090.             printf( "    0,\n" );
  1091.         }
  1092.         
  1093.         else
  1094.         mkdata( nultrans[i] );
  1095.         }
  1096.  
  1097.     dataend();
  1098.     }
  1099.  
  1100.     { /* spit out table mapping rules to line numbers */
  1101.     printf("#if YY_%s_DEBUG != 0\n",lexer_name);
  1102.     printf( C_short_decl, "yy_rule_linenum", num_rules );
  1103.     for ( i = 1; i < num_rules; ++i )
  1104.         mkdata( rule_linenum[i] );
  1105.     dataend();
  1106.     puts("#endif");
  1107.     }
  1108.  
  1109.     if ( reject )
  1110.     {
  1111.     /* declare state buffer variables */
  1112.     puts(
  1113.     "static yy_state_type yy_state_buf[YY_BUF_SIZE + 2], *yy_state_ptr;" );
  1114.     puts( "static YY_CHAR *yy_full_match;" );
  1115.     puts( "static int yy_lp;" );
  1116.  
  1117.     if ( variable_trailing_context_rules )
  1118.         {
  1119.         puts( "static int yy_looking_for_trail_begin = 0;" );
  1120.         puts( "static int yy_full_lp;" );
  1121.         puts( "static int *yy_full_state;" );
  1122.          printf( "#define YY_TRAILING_MASK 0x%x\n",
  1123.              (unsigned int) YY_TRAILING_MASK );
  1124.         printf( "#define YY_TRAILING_HEAD_MASK 0x%x\n",
  1125.              (unsigned int) YY_TRAILING_HEAD_MASK );
  1126.         }
  1127.  
  1128.     puts( "#define REJECT \\" );
  1129.         puts( "{ \\" );
  1130.         puts(
  1131.     "*yy_cp = yy_hold_char; /* undo effects of setting up yytext */ \\" );
  1132.         puts(
  1133.         "yy_cp = yy_full_match; /* restore poss. backed-over text */ \\" );
  1134.  
  1135.     if ( variable_trailing_context_rules )
  1136.         {
  1137.         puts( "yy_lp = yy_full_lp; /* restore orig. accepting pos. */ \\" );
  1138.         puts(
  1139.         "yy_state_ptr = yy_full_state; /* restore orig. state */ \\" );
  1140.         puts(
  1141.         "yy_current_state = *yy_state_ptr; /* restore curr. state */ \\" );
  1142.         }
  1143.  
  1144.         puts( "++yy_lp; \\" );
  1145.         puts( "goto find_rule; \\" );
  1146.         puts( "}" );
  1147.     }
  1148.     
  1149.     else
  1150.     {
  1151.     puts( "/* the intent behind this definition is that it'll catch" );
  1152.     puts( " * any uses of REJECT which flex missed" );
  1153.     puts( " */" );
  1154.     puts( "#define REJECT reject_used_but_not_detected" );
  1155.     }
  1156.     
  1157.     if ( yymore_used )
  1158.     {
  1159.     indent_puts( "static int yy_more_flag = 0;" );
  1160.     indent_puts( "static int yy_doing_yy_more = 0;" );
  1161.     indent_puts( "static int yy_more_len = 0;" );
  1162.     indent_puts(
  1163.         "#define yymore() { yy_more_flag = 1; }" );
  1164.     indent_puts(
  1165.         "#define YY_MORE_ADJ (yy_doing_yy_more ? yy_more_len : 0)" );
  1166.     }
  1167.  
  1168.     else
  1169.     {
  1170.     indent_puts( "#define yymore() yymore_used_but_not_detected" );
  1171.     indent_puts( "#define YY_MORE_ADJ 0" );
  1172.     }
  1173.  
  1174.     skelout();
  1175.  
  1176.     if ( ferror( temp_action_file ) )
  1177.     flexfatal( "error occurred when writing temporary action file" );
  1178.  
  1179.     else if ( fclose( temp_action_file ) )
  1180.     flexfatal( "error occurred when closing temporary action file" );
  1181.  
  1182.     temp_action_file = fopen( action_file_name, "r" );
  1183.  
  1184.     if ( temp_action_file == NULL )
  1185.     flexfatal( "could not re-open temporary action file" );
  1186.  
  1187.     /* copy prolog from action_file to output file */
  1188.     action_out();
  1189.  
  1190.     skelout();
  1191.  
  1192.     set_indent( 2 );
  1193.  
  1194.     if ( yymore_used )
  1195.     {
  1196.     indent_puts( "yy_more_len = 0;" );
  1197.     indent_puts( "yy_doing_yy_more = yy_more_flag;" );
  1198.     indent_puts( "if ( yy_doing_yy_more )" );
  1199.     indent_up();
  1200.     indent_puts( "{" );
  1201.     indent_puts( "yy_more_len = yy___leng;" );
  1202.     indent_puts( "yy_more_flag = 0;" );
  1203.     indent_puts( "}" );
  1204.     indent_down();
  1205.     }
  1206.  
  1207.     skelout();
  1208.  
  1209.     gen_start_state();
  1210.  
  1211.     /* note, don't use any indentation */
  1212.     puts( "yy_match:" );
  1213.     gen_next_match();
  1214.  
  1215.     skelout();
  1216.     set_indent( 2 );
  1217.     gen_find_action();
  1218.  
  1219.  
  1220.     /* copy actions from action_file to output file */
  1221.     skelout();
  1222.     indent_up();
  1223.     gen_bt_action();
  1224.     action_out();
  1225.  
  1226.     /* generate cases for any missing EOF rules */
  1227.     for ( i = 1; i <= lastsc; ++i )
  1228.     if ( ! sceof[i] )
  1229.         {
  1230.         do_indent();
  1231.         printf( "case YY_STATE_EOF(%s):\n", scname[i] );
  1232.         did_eof_rule = true;
  1233.         }
  1234.     
  1235.     if ( did_eof_rule )
  1236.     {
  1237.     indent_up();
  1238.     indent_puts( "yyterminate();" );
  1239.     indent_down();
  1240.     }
  1241.  
  1242.  
  1243.     /* generate code for handling NUL's, if needed */
  1244.  
  1245.     /* first, deal with backtracking and setting up yy_cp if the scanner
  1246.      * finds that it should JAM on the NUL
  1247.      */
  1248.     skelout();
  1249.     set_indent( 7 );
  1250.  
  1251.     if ( fullspd || fulltbl )
  1252.     indent_puts( "yy_cp = yy_c_buf_p;" );
  1253.     
  1254.     else
  1255.     { /* compressed table */
  1256.     if ( ! reject && ! interactive )
  1257.         {
  1258.         /* do the guaranteed-needed backtrack to figure out the match */
  1259.         indent_puts( "yy_cp = yy_last_accepting_cpos;" );
  1260.         indent_puts( "yy_current_state = yy_last_accepting_state;" );
  1261.         }
  1262.     }
  1263.  
  1264.  
  1265.     /* generate code for yy_get_previous_state() */
  1266.     set_indent( 1 );
  1267.     skelout();
  1268.  
  1269.     if ( bol_needed )
  1270.     indent_puts( "register YY_CHAR *yy_bp = yy___text;\n" );
  1271.  
  1272.     gen_start_state();
  1273.  
  1274.     set_indent( 2 );
  1275.     skelout();
  1276.     gen_next_state( true );
  1277.  
  1278.     set_indent( 1 );
  1279.     skelout();
  1280.     gen_NUL_trans();
  1281.  
  1282.     skelout();
  1283.  
  1284.     /* copy remainder of input to output */
  1285.  
  1286.     line_directive_out( stdout );
  1287.     (void) flexscan(); /* copy remainder of input to output */
  1288.     }
  1289.